<?php

namespace app\model\system;

use think\Model;
use think\model\concern\SoftDelete;

/**
 * 文件模型类
 * 负责处理文件上传、下载和管理相关的数据操作
 */
class File extends Model
{
    // 使用软删除
    use SoftDelete;

    // 设置表名
    protected $name = 'file';

    // 设置主键
    protected $pk = 'id';

    // 自动写入时间戳
    protected $autoWriteTimestamp = 'datetime';

    // 时间戳字段名称
    protected $createTime = 'create_time';
    protected $updateTime = 'update_time';
    protected $deleteTime = 'delete_time';

    // 类型转换
    protected $type = [
        'id' => 'integer',
        'admin_id' => 'integer',
        'file_name' => 'string',
        'file_size' => 'integer',
        'file_ext' => 'string',
        'file_path' => 'string',
        'file_hash' => 'string',
        'type' => 'string',
        'status' => 'integer',
        'download' => 'integer',
        'create_time' => 'int',
        'update_time' => 'int',
        'delete_time' => 'int',
    ];

    /**
     * 魔术方法，用于处理属性访问
     * 
     * @param string $name 属性名
     * @return mixed 属性值
     */
    public function __get($name)
    {
        // 显式处理id属性访问，消除IDE警告
        if ($name === 'id') {
            return $this->getData('id');
        }
        
        return parent::__get($name);
    }

    /**
     * 根据ID获取文件信息
     * 
     * @param int $id 文件ID
     * @return array|null 文件信息数组，如果不存在则返回null
     */
    public static function getFileInfoById(int $id): ?array
    {
        $file = self::find($id);
        if (!$file) {
            return null;
        }

        return $file->toArray();
    }

    /**
     * 根据ID数组批量获取文件信息
     * 
     * @param array $ids 文件ID数组
     * @return array 文件信息数组，键为ID，值为文件信息
     */
    public static function getFileInfoByIds(array $ids): array
    {
        if (empty($ids)) {
            return [];
        }

        $files = self::whereIn('id', $ids)->select();
        $result = [];

        foreach ($files as $file) {
            $result[$file->id] = $file->toArray();
        }

        return $result;
    }

    /**
     * 根据关联ID和类型获取附件列表
     * 
     * @param int $relatedId 关联ID
     * @param string $type 关联类型
     * @return array 附件列表
     */
    public static function getAttachmentsByRelated(int $relatedId, string $type): array
    {
        // 先查询关联表
        $relatedFiles = db('file_relation')
            ->where('related_id', $relatedId)
            ->where('type', $type)
            ->field('file_id')
            ->select();

        if (empty($relatedFiles)) {
            return [];
        }

        // 提取文件ID
        $fileIds = array_column($relatedFiles->toArray(), 'file_id');

        // 查询文件信息
        $files = self::whereIn('id', $fileIds)
            ->order('id', 'asc')
            ->select();

        $result = [];
        foreach ($files as $file) {
            $result[] = [
                'id' => $file->id,
                'file_name' => $file->file_name,
                'file_size' => $file->file_size,
                'file_ext' => $file->file_ext,
                'file_path' => $file->file_path,
                'download_url' => self::getDownloadUrl($file->id),
                'create_time' => $file->create_time
            ];
        }

        return $result;
    }

    /**
     * 获取文件下载URL
     * 
     * @param int $fileId 文件ID
     * @return string 下载URL
     */
    public static function getDownloadUrl(int $fileId): string
    {
        // 实际项目中可能需要根据配置生成不同的URL
        return '/api/file/download?id=' . $fileId;
    }

    /**
     * 上传文件并保存记录
     * 
     * @param array $fileInfo 文件信息
     * @param int $adminId 管理员ID
     * @param array $relatedInfo 关联信息（可选）
     * @return int|false 文件ID或false
     */
    public static function uploadFile(array $fileInfo, int $adminId, array $relatedInfo = [])
    {
        // 创建文件记录
        $file = new self();
        $file->admin_id = $adminId;
        $file->file_name = $fileInfo['name'];
        $file->file_size = $fileInfo['size'];
        $file->file_ext = pathinfo($fileInfo['name'], PATHINFO_EXTENSION);
        $file->file_path = $fileInfo['savepath'] . $fileInfo['savename'];
        $file->file_hash = md5_file($fileInfo['tmp_name']);
        $file->type = $fileInfo['type'];
        $file->status = 1;

        if ($file->save()) {
            // 如果有关联信息，创建关联记录
            if (!empty($relatedInfo) && isset($relatedInfo['related_id']) && isset($relatedInfo['type'])) {
                db('file_relation')->insert([
                    'file_id' => $file->id,
                    'related_id' => $relatedInfo['related_id'],
                    'type' => $relatedInfo['type'],
                    'create_time' => date('Y-m-d H:i:s')
                ]);
            }

            return $file->id;
        }

        return false;
    }

    /**
     * 更新文件下载次数
     * 
     * @param int $fileId 文件ID
     * @return bool 更新结果
     */
    public static function updateDownloadCount(int $fileId): bool
    {
        return self::where('id', $fileId)->inc('download', 1)->update([]) > 0;
    }

    /**
     * 获取文件大小的人性化表示
     * 
     * @param int $size 文件大小（字节）
     * @return string 人性化表示的文件大小
     */
    public static function getHumanFileSize(int $size): string
    {
        if ($size < 1024) {
            return $size . ' B';
        } elseif ($size < 1048576) {
            return round($size / 1024, 2) . ' KB';
        } elseif ($size < 1073741824) {
            return round($size / 1048576, 2) . ' MB';
        } else {
            return round($size / 1073741824, 2) . ' GB';
        }
    }
}